import config from "./config";
import { addCache, clearCache, getCache } from "./cache";
import { generateUniqueId } from "./utils";

const originalProto = XMLHttpRequest.prototype;
const originalOpen = originalProto.open;
const originalSend = originalProto.send;

export function isSupportSendBeacon() {
  return "sendBeacon" in navigator;
}

export function report(data) {
  if (!config.url) {
    console.error("请配置上报地址");
    return;
  }
  console.log("上报地址", config.url);

  const reportData = JSON.stringify({
    id: generateUniqueId(),
    data,
  });

  if (config.isImageUpload) {
    imgRequest(reportData);
  } else {
    // 发送数据 优先使用sendBeacon
    if (window.navigator.sendBeacon) {
      beaconRequest(reportData);
    } else {
      xhrRequest(config.url, reportData);
    }
  }
}

export function lazyReportBatch(data) {
  addCache(data);
  console.log(data, "上报的数据");

  const cache = getCache();
  if (cache.length && cache.length >= config.batchSize) {
    report(cache);
    console.log("批量上报成功");

    clearCache();
  }
}

// 使用图片上报
export function imgRequest(data) {
  const img = new Image();
  img.src = `${config.url}?data=${encodeURIComponent(JSON.stringify(data))}`;
}

// 使用ajax 上报
export function xhrRequest(url, data) {
  if (window.requestIdleCallback) {
    requestIdleCallback(() => {
      const xhr = new XMLHttpRequest();
      originalOpen.call(xhr, "POST", url);
      originalSend.call(xhr, JSON.stringify(data));
    }, 3000);
  } else {
    setTimeout(() => {
      const xhr = new XMLHttpRequest();
      originalOpen.call(xhr, "POST", url);
      originalSend.call(xhr, JSON.stringify(data));
    });
  }
}

const sendBeacon = isSupportSendBeacon() ? navigator.sendBeacon : xhrRequest;

// 使用beacon上报
export function beaconRequest(data) {
  if (window.requestIdleCallback) {
    window.requestIdleCallback(
      () => {
        if (sendBeacon === navigator.sendBeacon) {
          sendBeacon.call(navigator, config.url, data);
        } else {
          sendBeacon(config.url, data);
        }
      },
      { timeout: 3000 }
    );
  } else {
    setTimeout(() => {
      if (sendBeacon === navigator.sendBeacon) {
        sendBeacon.call(navigator, config.url, data);
      } else {
        sendBeacon(config.url, data);
      }
    });
  }
}
